package com.ev.asl.service.impl;

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ev.asl.constant.AslConstant;
import com.ev.asl.service.MoldingDailyService;
import com.ev.asl.service.FormingProductionStatisticsService;
import com.ev.asl.vo.*;
import com.ev.framework.utils.DateUtils;
import com.ev.mes.vo.WorkTimeVO;
import com.ev.scm.domain.StockDO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author 姚家乐
 * @since 2021/6/22 15:10
 */
@Service
public class FormingProductionStatisticsServiceImpl implements FormingProductionStatisticsService {
    @Autowired
    private MoldingDailyService moldingDailyService;

    @Override
    public FormingProductionStatisticsVo fpsAccounting(Map<String, Object> param) {

        List<Map<String, Object>> resultList = moldingDailyService.listForMap(param);

        int total = moldingDailyService.totalForMap(param);

        FormingProductionStatisticsVo formingProductionStatisticsVo = new FormingProductionStatisticsVo();

        formingProductionStatisticsVo.setTotal(total);

        //生产时间概况
        List<TimeProfile> timeProfiles = new ArrayList<>();

        //生产数量和
        BigDecimal totalMoldedQtyTotal = BigDecimal.ZERO;
        //不良数量和
        BigDecimal inspectionQtyTotal = BigDecimal.ZERO;
        //合格数量和
        BigDecimal qualifiedQtyTotal = BigDecimal.ZERO;
        //良品率
        BigDecimal yield = BigDecimal.ZERO;
        //出勤总人数
        BigDecimal attendanceTotal = BigDecimal.ZERO;

        //不良形态现况
        List<BadForm> badForms = new ArrayList<>();

        if (!CollectionUtils.isEmpty(resultList)) {
            for (Map<String, Object> stringObjectMap : resultList) {
                TimeProfile timeProfile = new TimeProfile();
                //日期
                timeProfile
                        .setDateString(DateUtils.format((Date) stringObjectMap.get("indicateDate")));
                timeProfile.setStartDate(DateUtils.format((Date) stringObjectMap.get("startDate"), DateUtils.DATE_TIME_PATTERN));
                timeProfile.setEndDate(DateUtils.format((Date) stringObjectMap.get("endDate"), DateUtils.DATE_TIME_PATTERN));

                String workTimeMapJson = String.valueOf(stringObjectMap.get("workTimeMap2"));
//                Map<String, Object> workTimeMap = JSON.parseObject(workTimeMapJson, HashMap.class);
                List<WorkTimeVO> workTimeMap = JSON.parseArray(workTimeMapJson, WorkTimeVO.class);

                //  选项1-排料时间；选项2-清扫时间；选项3-维修时间；选项4-开会时间；选项5-培训时间
                if (ObjectUtil.isNotEmpty(workTimeMap)) {
                    long zuoYe = workTimeMap.stream().filter(workTimeVO -> !ObjectUtils.isEmpty(workTimeVO.getValue1()) && !ObjectUtils.isEmpty(workTimeVO.getValue1().get(0)))
                            .map(workTimeVO -> DateUtil.between(workTimeVO.getValue1().get(0), workTimeVO.getValue1().get(1), DateUnit.MINUTE)).collect(Collectors.summarizingLong(time -> time)).getSum();
                    long paiLiao = workTimeMap.stream().filter(workTimeVO -> !ObjectUtils.isEmpty(workTimeVO.getValue2()) && !ObjectUtils.isEmpty(workTimeVO.getValue2().get(0)) && !ObjectUtils.isEmpty(workTimeVO.getValuething()) && workTimeVO.getValuething().equals("选项1"))
                            .map(workTimeVO -> DateUtil.between(workTimeVO.getValue2().get(0), workTimeVO.getValue2().get(1), DateUnit.MINUTE)).collect(Collectors.summarizingLong(time -> time)).getSum();
                    long qingSao = workTimeMap.stream().filter(workTimeVO -> !ObjectUtils.isEmpty(workTimeVO.getValue2()) && !ObjectUtils.isEmpty(workTimeVO.getValue2().get(0)) && !ObjectUtils.isEmpty(workTimeVO.getValuething()) && workTimeVO.getValuething().equals("选项2"))
                            .map(workTimeVO -> DateUtil.between(workTimeVO.getValue2().get(0), workTimeVO.getValue2().get(1), DateUnit.MINUTE)).collect(Collectors.summarizingLong(time -> time)).getSum();
                    long xuanXiang = workTimeMap.stream().filter(workTimeVO -> !ObjectUtils.isEmpty(workTimeVO.getValue2()) && !ObjectUtils.isEmpty(workTimeVO.getValue2().get(0)) && !ObjectUtils.isEmpty(workTimeVO.getValuething()) && workTimeVO.getValuething().equals("选项3"))
                            .map(workTimeVO -> DateUtil.between(workTimeVO.getValue2().get(0), workTimeVO.getValue2().get(1), DateUnit.MINUTE)).collect(Collectors.summarizingLong(time -> time)).getSum();
                    long kaiHui = workTimeMap.stream().filter(workTimeVO -> !ObjectUtils.isEmpty(workTimeVO.getValue2()) && !ObjectUtils.isEmpty(workTimeVO.getValue2().get(0)) && !ObjectUtils.isEmpty(workTimeVO.getValuething()) && workTimeVO.getValuething().equals("选项4"))
                            .map(workTimeVO -> DateUtil.between(workTimeVO.getValue2().get(0), workTimeVO.getValue2().get(1), DateUnit.MINUTE)).collect(Collectors.summarizingLong(time -> time)).getSum();
                    long peiXun = workTimeMap.stream().filter(workTimeVO -> !ObjectUtils.isEmpty(workTimeVO.getValue2()) && !ObjectUtils.isEmpty(workTimeVO.getValue2().get(0)) && !ObjectUtils.isEmpty(workTimeVO.getValuething()) && workTimeVO.getValuething().equals("选项5"))
                            .map(workTimeVO -> DateUtil.between(workTimeVO.getValue2().get(0), workTimeVO.getValue2().get(1), DateUnit.MINUTE)).collect(Collectors.summarizingLong(time -> time)).getSum();
                    long baoYang = workTimeMap.stream().filter(workTimeVO -> !ObjectUtils.isEmpty(workTimeVO.getValue2()) && !ObjectUtils.isEmpty(workTimeVO.getValue2().get(0)) && !ObjectUtils.isEmpty(workTimeVO.getValuething()) && workTimeVO.getValuething().equals("选项6"))
                            .map(workTimeVO -> DateUtil.between(workTimeVO.getValue2().get(0), workTimeVO.getValue2().get(1), DateUnit.MINUTE)).collect(Collectors.summarizingLong(time -> time)).getSum();
                    long qiTa = workTimeMap.stream().filter(workTimeVO -> !ObjectUtils.isEmpty(workTimeVO.getValue2()) && !ObjectUtils.isEmpty(workTimeVO.getValue2().get(0)) && !ObjectUtils.isEmpty(workTimeVO.getValuething()) && workTimeVO.getValuething().equals("选项7"))
                            .map(workTimeVO -> DateUtil.between(workTimeVO.getValue2().get(0), workTimeVO.getValue2().get(1), DateUnit.MINUTE)).collect(Collectors.summarizingLong(time -> time)).getSum();

//                    BigDecimal hour = new BigDecimal(60);
                    BigDecimal hour = new BigDecimal(1);
                    timeProfile.setWorkingHours((zuoYe == 0l) ? BigDecimal.ZERO : new BigDecimal(zuoYe + "").divide(hour, 4, RoundingMode.HALF_UP));
                    timeProfile.setDischargingTime((paiLiao == 0l) ? BigDecimal.ZERO : new BigDecimal(paiLiao + "").divide(hour, 4, RoundingMode.HALF_UP));
                    timeProfile.setCleaningTime((qingSao == 0l) ? BigDecimal.ZERO : new BigDecimal(qingSao + "").divide(hour, 4, RoundingMode.HALF_UP));
                    timeProfile.setMaintenanceTime((xuanXiang == 0l) ? BigDecimal.ZERO : new BigDecimal(xuanXiang + "").divide(hour, 4, RoundingMode.HALF_UP));
                    timeProfile.setMeetingTime((kaiHui == 0l) ? BigDecimal.ZERO : new BigDecimal(kaiHui + "").divide(hour, 4, RoundingMode.HALF_UP));
                    timeProfile.setTrainingTime((peiXun == 0l) ? BigDecimal.ZERO : new BigDecimal(peiXun + "").divide(hour, 4, RoundingMode.HALF_UP));
                    timeProfile.setUpkeepTime((baoYang == 0l) ? BigDecimal.ZERO : new BigDecimal(baoYang + "").divide(hour, 4, RoundingMode.HALF_UP));
                    timeProfile.setOtherTime((qiTa == 0l) ? BigDecimal.ZERO : new BigDecimal(qiTa + "").divide(hour, 4, RoundingMode.HALF_UP));
                    //实际出勤人数
                    timeProfile.setAttendance(stringObjectMap.containsKey("realAttendance") ? Integer.parseInt(stringObjectMap.get("realAttendance").toString()) : 0);
                    //合格数量
                    timeProfile.setQualifiedQty(stringObjectMap.containsKey("productionQty") ? new BigDecimal(stringObjectMap.get("productionQty").toString()) : new BigDecimal(AslConstant.ZERO));
                    //不良数量
                    timeProfile.setInspectionQty(stringObjectMap.containsKey("inspectionQty") ? new BigDecimal(stringObjectMap.get("inspectionQty").toString()) : new BigDecimal(AslConstant.ZERO));

                    attendanceTotal = attendanceTotal.add(new BigDecimal(timeProfile.getAttendance()));

                    timeProfiles.add(timeProfile);
                }
//                BigDecimal one = this.getHour2(workTimeMap,"startTime1","endTime1");
//
//                BigDecimal two = this.getHour2(workTimeMap,"startTime2","endTime2");
//
//                BigDecimal three = this.getHour2(workTimeMap,"startTime3","endTime3");
//
//                BigDecimal four = this.getHour2(workTimeMap,"startTime4","endTime4");
//
//                BigDecimal five = this.getHour2(workTimeMap,"startTime5","endTime5");
//
//                BigDecimal six = this.getHour2(workTimeMap,"startTime6","endTime6");
//
//                BigDecimal seven = this.getHour2(workTimeMap,"startTime7","endTime7");
//
//                BigDecimal eight = this.getHour2(workTimeMap,"startTime8","endTime8");
//
//                BigDecimal nine = this.getHour2(workTimeMap,"startTime9","endTime9");
//
//                BigDecimal ten = this.getHour2(workTimeMap,"startTime10","endTime10");

//                BigDecimal workingHours = BigDecimal.ZERO;
//                workingHours = workingHours.add(one).add(two).add(three).add(four).add(five).setScale(2,
//                        BigDecimal.ROUND_HALF_UP);

//                BigDecimal workingHours = BigDecimal.ZERO;
//                workingHours = workingHours.add(one).add(three).add(five).add(seven).add(nine).setScale(2,
//                        BigDecimal.ROUND_HALF_UP);
//
//                BigDecimal dischargingTime = BigDecimal.ZERO;
//                dischargingTime = dischargingTime.add(two).setScale(2, BigDecimal.ROUND_HALF_UP);
//
//                BigDecimal cleaningTime = BigDecimal.ZERO;
//                cleaningTime = cleaningTime.add(four).setScale(2, BigDecimal.ROUND_HALF_UP);
//
//                BigDecimal maintenanceTime = BigDecimal.ZERO;
//                maintenanceTime = maintenanceTime.add(six).setScale(2, BigDecimal.ROUND_HALF_UP);
//
//                BigDecimal meetingTime = BigDecimal.ZERO;
//                meetingTime = meetingTime.add(eight).setScale(2, BigDecimal.ROUND_HALF_UP);
//
//                BigDecimal trainingTime = BigDecimal.ZERO;
//                trainingTime = trainingTime.add(ten).setScale(2, BigDecimal.ROUND_HALF_UP);

//                作业时间
//                timeProfile.setWorkingHours(workingHours);
//                //排料时间
//                timeProfile.setDischargingTime(dischargingTime);
//                //清扫时间
//                timeProfile.setCleaningTime(cleaningTime);
//                //维修时间
//                timeProfile.setMaintenanceTime(maintenanceTime);
//                //开会时间
//                timeProfile.setMeetingTime(meetingTime);
//                //培训时间
//                timeProfile.setTrainingTime(trainingTime);
//                timeProfiles.add(timeProfile);

                //生产数量
                BigDecimal totalMoldedQty = new BigDecimal(
                        String.valueOf(stringObjectMap.get("instructionQty") != null
                                ? stringObjectMap.get("instructionQty")
                                : "0"));
//                BigDecimal instructionQty = new BigDecimal(
//                        String.valueOf(stringObjectMap.get("productionQty") != null
//                                ? stringObjectMap.get("productionQty")
//                                : "0"));

//                totalMoldedQtyTotal = totalMoldedQtyTotal.add(totalMoldedQty)
//                    .setScale(AslConstant.ZERO, BigDecimal.ROUND_HALF_UP);
                //不良数量
                BigDecimal inspectionQty = new BigDecimal(
                        String.valueOf(stringObjectMap.get("inspectionQty") != null
                                ? stringObjectMap.get("inspectionQty")
                                : "0"));
                inspectionQtyTotal = inspectionQtyTotal.add(inspectionQty)
                        .setScale(AslConstant.ZERO, BigDecimal.ROUND_HALF_UP);
                //合格数量
                BigDecimal qualifiedQty = ObjectUtil.isEmpty(stringObjectMap.get("productionQty")) ? BigDecimal.ZERO : new BigDecimal(stringObjectMap.get("productionQty").toString());
//                BigDecimal qualifiedQty = totalMoldedQty.subtract(inspectionQty);
                qualifiedQtyTotal = qualifiedQtyTotal.add(qualifiedQty).setScale(AslConstant.ZERO,
                        BigDecimal.ROUND_HALF_UP);
                totalMoldedQtyTotal = inspectionQtyTotal.add(qualifiedQtyTotal);
                String badSituation = String.valueOf(stringObjectMap.get("badSituation"));
                JSONArray badSituationArray = JSON.parseArray(badSituation);
                if (!ObjectUtils.isEmpty(badSituationArray) && badSituationArray.size() > 0) {
                    for (Object o : badSituationArray) {
                        BadForm badForm = new BadForm();
                        JSONObject jsonObject = JSON.parseObject(o.toString());
                        badForm
                                .setBadItemKeyId(StringUtils.isBlank(String.valueOf(jsonObject.get("id"))) ? null : Integer.parseInt(String.valueOf(jsonObject.get("id"))));
                        badForm.setBadItemKey(ObjectUtils.isEmpty(jsonObject.get("name")) ? null : String.valueOf(jsonObject.get("name")));
                        badForm
                                .setBadItemValue(StringUtils.isBlank(String.valueOf(jsonObject.get("count"))) ? null : new BigDecimal(String.valueOf(jsonObject.get("count"))));
                        badForms.add(badForm);
                    }
                }
            }
            BigDecimal zero = new BigDecimal(0);
            if (!totalMoldedQtyTotal.equals(zero) && !qualifiedQtyTotal.equals(zero)) {
                yield = qualifiedQtyTotal.divide(totalMoldedQtyTotal, AslConstant.TWO,
                        BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal("100"));
            }

            // 生产实绩概况
            ActualSituation actualSituation = new ActualSituation();
            actualSituation.setTotalMoldedQty(totalMoldedQtyTotal);
            actualSituation.setQualifiedQty(qualifiedQtyTotal);
            actualSituation.setInspectionQty(inspectionQtyTotal);
            actualSituation.setYield(yield);

            List<BadForm> badFormss = new ArrayList<>(badForms.stream()
                    .collect(Collectors.toMap(BadForm::getBadItemKey, a -> a, (o1, o2) -> {
                        o1.setBadItemValue(o1.getBadItemValue().add(o2.getBadItemValue()));
                        return o1;
                    })).values());
            BigDecimal workingHoursTtl = BigDecimal.ZERO;
            BigDecimal dischargingTimeTtl = BigDecimal.ZERO;
            BigDecimal cleaningTimeTtl = BigDecimal.ZERO;
            BigDecimal maintenanceTimeTtl = BigDecimal.ZERO;
            BigDecimal meetingTimeTtl = BigDecimal.ZERO;
            BigDecimal trainingTimeTtl = BigDecimal.ZERO;
            BigDecimal upkeepTimeTtl = BigDecimal.ZERO;
            BigDecimal otherTimeTtl = BigDecimal.ZERO;
            BigDecimal ttlTimeTtl = BigDecimal.ZERO;
            if (!ObjectUtils.isEmpty(timeProfiles) && timeProfiles.size() > 0) {
                for (TimeProfile timeProfile : timeProfiles) {
                    BigDecimal ttlTime = BigDecimal.ZERO;
                    ttlTime = ttlTime
                            .add(timeProfile.getCleaningTime() != null ? timeProfile.getCleaningTime()
                                    : BigDecimal.ZERO);
                    ttlTime = ttlTime
                            .add(timeProfile.getDischargingTime() != null ? timeProfile.getDischargingTime()
                                    : BigDecimal.ZERO);
                    ttlTime = ttlTime
                            .add(timeProfile.getMaintenanceTime() != null ? timeProfile.getMaintenanceTime()
                                    : BigDecimal.ZERO);
                    ttlTime = ttlTime
                            .add(timeProfile.getMeetingTime() != null ? timeProfile.getMeetingTime()
                                    : BigDecimal.ZERO);
                    ttlTime = ttlTime
                            .add(timeProfile.getTrainingTime() != null ? timeProfile.getTrainingTime()
                                    : BigDecimal.ZERO);
                    ttlTime = ttlTime
                            .add(timeProfile.getWorkingHours() != null ? timeProfile.getWorkingHours()
                                    : BigDecimal.ZERO);
                    ttlTime = ttlTime
                            .add(timeProfile.getUpkeepTime() != null ? timeProfile.getUpkeepTime()
                                    : BigDecimal.ZERO);
                    ttlTime = ttlTime
                            .add(timeProfile.getOtherTime() != null ? timeProfile.getOtherTime()
                                    : BigDecimal.ZERO);

                    timeProfile.setTtlTime(ttlTime);

                    workingHoursTtl = workingHoursTtl
                            .add(timeProfile.getWorkingHours() != null ? timeProfile.getWorkingHours()
                                    : BigDecimal.ZERO);
                    dischargingTimeTtl = dischargingTimeTtl
                            .add(timeProfile.getDischargingTime() != null ? timeProfile.getDischargingTime()
                                    : BigDecimal.ZERO);
                    cleaningTimeTtl = cleaningTimeTtl
                            .add(timeProfile.getCleaningTime() != null ? timeProfile.getCleaningTime()
                                    : BigDecimal.ZERO);
                    maintenanceTimeTtl = maintenanceTimeTtl
                            .add(timeProfile.getMaintenanceTime() != null ? timeProfile.getMaintenanceTime()
                                    : BigDecimal.ZERO);
                    meetingTimeTtl = meetingTimeTtl
                            .add(timeProfile.getMeetingTime() != null ? timeProfile.getMeetingTime()
                                    : BigDecimal.ZERO);
                    trainingTimeTtl = trainingTimeTtl
                            .add(timeProfile.getTrainingTime() != null ? timeProfile.getTrainingTime()
                                    : BigDecimal.ZERO);
                    upkeepTimeTtl = upkeepTimeTtl
                            .add(timeProfile.getUpkeepTime() != null ? timeProfile.getUpkeepTime()
                                    : BigDecimal.ZERO);
                    otherTimeTtl = otherTimeTtl
                            .add(timeProfile.getOtherTime() != null ? timeProfile.getOtherTime()
                                    : BigDecimal.ZERO);
                    ttlTimeTtl = ttlTimeTtl.add(
                            timeProfile.getTtlTime() != null ? timeProfile.getTtlTime() : BigDecimal.ZERO);
                }
            }
            formingProductionStatisticsVo.setWorkingHoursTtl(workingHoursTtl);
            formingProductionStatisticsVo.setDischargingTimeTtl(dischargingTimeTtl);
            formingProductionStatisticsVo.setCleaningTimeTtl(cleaningTimeTtl);
            formingProductionStatisticsVo.setMaintenanceTimeTtl(maintenanceTimeTtl);
            formingProductionStatisticsVo.setMeetingTimeTtl(meetingTimeTtl);
            formingProductionStatisticsVo.setTrainingTimeTtl(trainingTimeTtl);
            formingProductionStatisticsVo.setUpkeepTimeTtl(upkeepTimeTtl);
            formingProductionStatisticsVo.setOtherTimeTtl(otherTimeTtl);
            formingProductionStatisticsVo.setTtlTimeTtl(ttlTimeTtl);

            formingProductionStatisticsVo.setTimeProfiles(timeProfiles);
            formingProductionStatisticsVo.setActualSituation(actualSituation);
            formingProductionStatisticsVo.setBadForms(badFormss);
            formingProductionStatisticsVo.setAttendanceTotal(attendanceTotal);
            BigDecimal badFormQtyTotal = BigDecimal.ZERO;
            for (BadForm badForm : badFormss) {
                badFormQtyTotal = badFormQtyTotal.add(badForm.getBadItemValue());
            }
            formingProductionStatisticsVo.setBadFormQtyTotal(badFormQtyTotal);
            MoldingDuty moldingDuty = new MoldingDuty();
            moldingDuty.setQualifiedQtya(qualifiedQtyTotal);
            BigDecimal jobTime = BigDecimal.ZERO;
            if (!ObjectUtils.isEmpty(timeProfiles) && timeProfiles.size() > 0) {
                for (TimeProfile o : timeProfiles) {
                    jobTime = jobTime.add(o.getWorkingHours());
                }
            }
            moldingDuty.setJobTime(jobTime);
            moldingDuty.setMoldingDuty(BigDecimal.ZERO);
            if (!jobTime.equals(new BigDecimal("0"))) {
                jobTime = jobTime.divide(new BigDecimal(60), AslConstant.ZERO, BigDecimal.ROUND_HALF_UP);
                moldingDuty.setMoldingDuty(
                        qualifiedQtyTotal.divide(jobTime, AslConstant.TWO, BigDecimal.ROUND_HALF_UP));
            }
            formingProductionStatisticsVo.setMoldingDuty(moldingDuty);
            return formingProductionStatisticsVo;
        }
        return formingProductionStatisticsVo;
    }

    private BigDecimal getHour(Map<String, Object> workTimeMap, String start, String end) {
        String stringNull = "";
        BigDecimal hourInterval = BigDecimal.ZERO;
        if ((Objects.nonNull(workTimeMap.get(start))
                && !stringNull.equals(String.valueOf(workTimeMap.get(start))))
                && (Objects.nonNull(workTimeMap.get(end))
                && !stringNull.equals(String.valueOf(workTimeMap.get(end))))) {
            Date startTime = DateUtils.getDate(String.valueOf(workTimeMap.get(start)));
            Date endTime = DateUtils.getDate(String.valueOf(workTimeMap.get(end)));
            hourInterval = new BigDecimal(
                    String.valueOf(DateUtils.getHourInterval(startTime, endTime)));
        }
        return hourInterval;
    }

    private BigDecimal getHour2(Map<String, Object> workTimeMap, String start, String end) {
        String stringNull = "";
        BigDecimal hourInterval = BigDecimal.ZERO;
        if ((Objects.nonNull(workTimeMap.get(start))
                && !stringNull.equals(String.valueOf(workTimeMap.get(start))))
                && (Objects.nonNull(workTimeMap.get(end))
                && !stringNull.equals(String.valueOf(workTimeMap.get(end))))) {
            Date startTime = DateUtils.getDate(String.valueOf(workTimeMap.get(start)));
            Date endTime = DateUtils.getDate(String.valueOf(workTimeMap.get(end)));
            hourInterval = new BigDecimal(
                    String.valueOf(DateUtils.getHourInterval2(startTime, endTime)));
        }
        return hourInterval;
    }

}
